<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <meta charset="utf-8">
  <script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
  <script src="../../../web-component-tester/browser.js"></script>
  <link rel="import" href="../../polymer.html">
  <link rel="import" href="array-selector-elements.html">
<body>

<array-selector id="singleConfigured"
  items='[{"name": "one"},{"name": "two"},{"name": "three"}]'>
</array-selector>

<array-selector id="multiConfigured" multi
  items='[{"name": "one"},{"name": "two"},{"name": "three"}]'>
</array-selector>

<template is="dom-bind" id="bind">
  <observe-el id="observer" single-selected="{{singleSelected}}" multi-selected="{{multiSelected}}"></observe-el>
  <array-selector id="singleBound" items="{{items}}" selected="{{singleSelected}}"></array-selector>
  <array-selector id="multiBound" items="{{items}}" selected="{{multiSelected}}" multi></array-selector>
</template>

<script>
/* global bind observer singleBound multiBound */
suite('basic', function() {
  test('single selection', function() {
    var el = document.querySelector('#singleConfigured');
    // Nothing selected
    assert.strictEqual(el.selectedItem, null);
    assert.isFalse(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Select 0
    el.select(el.items[0]);
    assert.strictEqual(el.selectedItem, el.items[0]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Re-select 0
    el.select(el.items[0]);
    assert.strictEqual(el.selectedItem, el.items[0]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Select 2
    el.select(el.items[2]);
    assert.strictEqual(el.selectedItem, el.items[2]);
    assert.isFalse(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isTrue(el.isSelected(el.items[2]));
    // Toggle 2
    el.toggle = true;
    el.select(el.items[2]);
    assert.strictEqual(el.selectedItem, null);
    assert.isFalse(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Toggle 2
    el.toggle = true;
    el.select(el.items[2]);
    assert.strictEqual(el.selectedItem, el.items[2]);
    assert.isFalse(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isTrue(el.isSelected(el.items[2]));
  });

  test('multiple selection', function() {
    var el = document.querySelector('#multiConfigured');
    // Nothing selected
    assert.sameMembers(el.selected, []);
    assert.isFalse(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Select 0
    el.select(el.items[0]);
    assert.sameMembers(el.selected, [el.items[0]]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Re-select 0
    el.select(el.items[0]);
    assert.sameMembers(el.selected, [el.items[0]]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Select 2
    el.select(el.items[2]);
    assert.sameMembers(el.selected, [el.items[0], el.items[2]]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isTrue(el.isSelected(el.items[2]));
    // Toggle 2
    el.toggle = true;
    el.select(el.items[2]);
    assert.sameMembers(el.selected, [el.items[0]]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isFalse(el.isSelected(el.items[2]));
    // Toggle 2
    el.toggle = true;
    el.select(el.items[2]);
    assert.sameMembers(el.selected, [el.items[0], el.items[2]]);
    assert.isTrue(el.isSelected(el.items[0]));
    assert.isFalse(el.isSelected(el.items[1]));
    assert.isTrue(el.isSelected(el.items[2]));
  });

  test('bound defaults', function() {
    assert.equal(bind.$.observer.singleSelected, null);
    assert.sameMembers(bind.$.observer.multiSelected, []);
    bind.items = [
      {name: 'one'},
      {name: 'two'},
      {name: 'three'}
    ];
    assert.equal(bind.$.observer.singleSelected, null);
    assert.sameMembers(bind.$.observer.multiSelected, []);
  });

  test('single selection notification', function() {
    bind.items = [
      {name: 'one'},
      {name: 'two'},
      {name: 'three'}
    ];
    var called = false;
    observer.singleChanged = function(info) {
      called = true;
      assert.equal(info.path, 'singleSelected');
      assert.equal(info.value, bind.items[2]);
      assert.equal(bind.$.observer.singleSelected, bind.items[2]);
    };
    singleBound.select(bind.items[2]);
    assert.equal(called, true);
    observer.singleChanged = function() {};
  });

  test('single selection sub-property change', function() {
    var called = false;
    observer.singleChanged = function(info) {
      called = true;
      assert.equal(info.path, 'singleSelected.name');
      assert.equal(info.value, 'test');
      assert.equal(bind.$.observer.singleSelected.name, 'test');
    };
    bind.set(['items', 2, 'name'], 'test');
    assert.equal(called, true);
    observer.singleChanged = function() {};
  });

  test('single selection sub-property change after unshift', function() {
    var called = false;
    observer.singleChanged = function(info) {
      called = true;
      assert.equal(info.path, 'singleSelected.name');
      assert.equal(info.value, 'test2');
      assert.equal(bind.$.observer.singleSelected.name, 'test2');
    };
    bind.unshift('items', {name: 'zero'});
    bind.set(['items', 3, 'name'], 'test2');
    assert.equal(called, true);
    observer.singleChanged = function() {};
  });

  test('multi selection notification', function() {
    bind.items = [
      {name: 'one'},
      {name: 'two'},
      {name: 'three'}
    ];
    var called = false;
    observer.multiChanged = function(info) {
      if (info.path == 'multiSelected.length') {
        assert.equal(info.value, 1);
      } else {
        called = true;
        assert.equal(info.path, 'multiSelected.splices');
        assert.equal(info.value.keySplices.length, 1);
        assert.equal(info.value.keySplices[0].added.length, 1);
        assert.equal(info.value.keySplices[0].added[0], '#0');
        assert.equal(info.value.keySplices[0].removed.length, 0);
        assert.sameMembers(bind.$.observer.multiSelected, [bind.items[2]]);
      }
    };
    multiBound.select(bind.items[2]);
    called = false;
    observer.multiChanged = function(info) {
      called = true;
      if (info.path == 'multiSelected.length') {
        assert.equal(info.value, 2);
      } else {
        assert.equal(info.path, 'multiSelected.splices');
        assert.equal(info.value.keySplices.length, 1);
        assert.equal(info.value.keySplices[0].added.length, 1);
        assert.equal(info.value.keySplices[0].added[0], '#1');
        assert.equal(info.value.keySplices[0].removed.length, 0);
        assert.sameMembers(bind.$.observer.multiSelected, [bind.items[2], bind.items[0]]);
      }
    };
    multiBound.select(bind.items[0]);
    assert.equal(called, true);
    observer.multiChanged = function() {};
  });

  test('multi selection sub-property change', function() {
    var called = false;
    observer.multiChanged = function(info) {
      called = true;
      assert.equal(info.path, 'multiSelected.#0.name');
      assert.equal(info.value, 'test');
      assert.equal(bind.$.observer.multiSelected[0].name, 'test');
    };
    bind.set(['items', 2, 'name'], 'test');
    observer.multiChanged = function(info) {
      called = true;
      assert.equal(info.path, 'multiSelected.#1.name');
      assert.equal(info.value, 'test2');
      assert.equal(bind.$.observer.multiSelected[1].name, 'test2');
    };
    bind.set(['items', 0, 'name'], 'test2');
    assert.equal(called, true);
    observer.multiChanged = function() {};
  });


  test('multi selection sub-property change after unshift', function() {
    var called = false;
    observer.multiChanged = function(info) {
      called = true;
      assert.equal(info.path, 'multiSelected.#1.name');
      assert.equal(info.value, 'test3');
      assert.equal(bind.$.observer.multiSelected[1].name, 'test3');
    };
    bind.unshift('items', {name: 'zero'});
    bind.set(['items', 1, 'name'], 'test3');
    assert.equal(called, true);
  });

});
</script>

</body>
</html>
